package com.xplay.xpocker.room.mahjong;

import com.xplay.xpocker.constant.RoomTypeEnum;
import com.xplay.xpocker.dvo.AbstractRoom;
import com.xplay.xpocker.dvo.GameRuMahjongUserState;
import com.xplay.xpocker.entity.GameHiRoomDTO;
import com.xplay.xpocker.entity.GameRuMahjongLogs;
import com.xplay.xpocker.room.mahjong.dto.EFScoreInfo;
import com.xplay.xpocker.room.mahjong.dto.MahjongRoomInfo;
import com.xplay.xpocker.room.mahjong.dto.MahjongRoomRule;
import com.xplay.xpocker.room.mahjong.dto.ScoreInfo;
import com.xplay.xpocker.room.mahjong.util.MahjongHuUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

public abstract class AbstractIsolationEventStrategy extends AbstractMahjongAction {

    /**
     * TODO
     * 这个类涉及到改造
     * 先提供默认方法
     */

    @Autowired
    public ApplicationEventPublisher applicationEventPublisher;

    private static final ConcurrentHashMap<String, AbstractIsolationEventStrategy> ROOM_SETTLEMENT_STRATEGY = new ConcurrentHashMap<>();

    protected abstract RoomTypeEnum strategyName();

    @PostConstruct
    public void registerFactory() {
        ROOM_SETTLEMENT_STRATEGY.put(strategyName().getCode(), this);
    }

    public static AbstractIsolationEventStrategy getSettlementStrategy(String type) {
        return ROOM_SETTLEMENT_STRATEGY.get(type);
    }

    /**
     * @param currentUser 当前杠牌人
     * @param exportUser  谁导致当前杠牌人
     * @param type        杠牌类型
     * @param card        杠的什么牌
     * @param roomInfo    房间所有信息
     * @return
     */
    public abstract void settlementBar(GameRuMahjongUserState currentUser, GameRuMahjongUserState exportUser, Integer type, Integer card, AbstractRoom<MahjongRoomRule, MahjongRoomInfo, GameRuMahjongLogs> roomInfo);

    /**
     * 胡牌结算
     *
     * @return
     */
    public abstract void settlementHu(GameRuMahjongUserState currentUser, GameRuMahjongUserState exportUser, Integer exportCard, AbstractRoom<MahjongRoomRule, MahjongRoomInfo, GameRuMahjongLogs> roomInfo);

    /**
     * 执行游戏结算
     * @param roomInfo
     * @param gameHiRoomDTO
     */

    public abstract void presentSettlement(AbstractRoom<MahjongRoomRule, MahjongRoomInfo, GameRuMahjongLogs> roomInfo, GameHiRoomDTO gameHiRoomDTO);

    public abstract ScoreInfo checkHu(GameRuMahjongUserState currentUser, GameRuMahjongUserState exportUser, Integer card, AbstractRoom<MahjongRoomRule, MahjongRoomInfo, GameRuMahjongLogs> roomInfo);


    /**
     * 一些检测
     *
     * @param roomInfo
     */

    public abstract void checkUserAction(AbstractRoom<MahjongRoomRule, MahjongRoomInfo, GameRuMahjongLogs> roomInfo);

    /**
     * 游戏开始事件检测
     *
     * @param roomInfo
     */

    public abstract void gameStartActionCheck(AbstractRoom<MahjongRoomRule, MahjongRoomInfo, GameRuMahjongLogs> roomInfo);

    /**
     * 出牌事件检测
     *
     * @param current
     * @param exportCard
     * @param roomInfo
     * @return
     */
    public abstract boolean exportCardActionCheck(GameRuMahjongUserState current, Integer exportCard, AbstractRoom<MahjongRoomRule, MahjongRoomInfo, GameRuMahjongLogs> roomInfo);

    /**
     * 发牌 事件检测
     *
     * @param nextUser
     * @param nextCard
     * @param roomInfo
     */
    public abstract void dealCardActionCheck(GameRuMahjongUserState nextUser, Integer nextCard, AbstractRoom<MahjongRoomRule, MahjongRoomInfo, GameRuMahjongLogs> roomInfo);

    /**
     * 通过用户的手牌判断能听那些牌
     *
     * @param currentUser
     * @return
     */
    public abstract List<EFScoreInfo> checkListenCards(GameRuMahjongUserState currentUser, AbstractRoom<MahjongRoomRule, MahjongRoomInfo, GameRuMahjongLogs> roomInfo);

    /**
     * 通过用户的手牌判断 出哪些牌能听那些牌
     *
     * @param currentUser
     * @return
     */
    public abstract List<MahjongHuUtil.CardEHInfo> checkExportListenCards(GameRuMahjongUserState currentUser);

    /**
     * 碰牌事件检测
     *
     * @param roomInfo
     * @param current
     * @param source
     * @param cardCode
     */
    public abstract void bumpCardActionCheck(AbstractRoom<MahjongRoomRule, MahjongRoomInfo, GameRuMahjongLogs> roomInfo,
                                             GameRuMahjongUserState current,
                                             GameRuMahjongUserState source,
                                             Integer cardCode);
}
